﻿using CRM.Models;
using CRM.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CRM.Services;
using Microsoft.AspNetCore.Identity;
using CRM.Services.Customer;
using CRM.ViewModels.Customer;
using static CRM.Services.Customer.CustomerService;
using Z.EntityFramework.Plus;
using static CRM.Models.CustomerCompany;

namespace CRM.Controllers.Customer
{
    using CustomerModel = CRM.Models.Customer;
    using UserModel = CRM.Models.User;

    [Route("api/[controller]")]
    [ApiController]
    public class BlockController : BaseController
    {
        private readonly MyDbContext _dbContext;
        private readonly UserManager<User> _userManager;
        private readonly CustomerService _customerService;

        public BlockController(MyDbContext dbContext, UserManager<User> userManager, CustomerService customerService)
        {
            _dbContext = dbContext;
            _userManager = userManager;
            _customerService = customerService;
        }

        [HttpPost(nameof(List))]
        public async Task<ResultStruct> List(CustomerListVM Scope)
        {
            var Model = _customerService.BlockSelectionRange(Scope.Action, Scope.Type);

            if (!string.IsNullOrEmpty(_customerService.Error))
            {
                return Error(new object(), _customerService.Error);
            }

            var user = await _userManager.GetUserAsync(User);

            if (!string.IsNullOrEmpty(Scope.UpdatedAtStart.ToString()))
            {
                Model = Model.Where(m => m.UpdatedAt >= Scope.UpdatedAtStart && m.UpdatedAt <= Scope.UpdatedAtEnd);
            }

            var List = await Model
                .OrderByDescending(m => m.Id)
                .Include(m => m.User)
                .Include(m => m.DiyGroup)
                .Include(m => m.Source)
                .Include(m => m.Labels)
                .OrderByDescending(m => m.UpdatedAt)
                .AsSplitQuery()
                .ToPaginateAsync(Request);

            return Success(List);
        }

        [HttpPost(nameof(CustomerExportList))]
        public async Task<ResultStruct> CustomerExportList(CustomerListVM Scope)
        {
            var user = await _userManager.GetUserAsync(User);
            var BlockIdsInt = await GetBlockIdsByCondition(Scope);

            var CustomerModel = user.SettingsObj.OnlyExportValidEmails
                ? _customerService.CustomerWithValidEmailCondition()
                : _customerService.CustomerCondition();

            CustomerModel = CustomerModel.Where(m => BlockIdsInt.Contains(m.BlockId));


            var List = await CustomerModel.Select(m => new
                {
                    Id = m.Id,
                    Name = m.Name,
                    Email = m.Email,
                    m.PersonalEmail
                })
                .ToListAsync();

            return Success(List);
        }

        [HttpPost("[action]")]
        public async Task<ResultStruct> CustomerExportBlockIds(CustomerListVM scope)
        {
            var blockIds = await GetBlockIdsByCondition(scope);

            return Success(blockIds);
        }

        private async Task<int[]> GetBlockIdsByCondition(CustomerListVM scope)
        {
            var blockModel = _customerService.BlockSelectionRange(scope.Action, scope.Type);

            if (!string.IsNullOrEmpty(_customerService.Error))
            {
                return Enumerable.Empty<int>().ToArray();
            }

            if (!string.IsNullOrEmpty(scope.UpdatedAtStart.ToString()))
            {
                blockModel = blockModel.Where(m =>
                    m.UpdatedAt >= scope.UpdatedAtStart && m.UpdatedAt <= scope.UpdatedAtEnd);
            }

            return await blockModel.Select(m => m.Id).ToArrayAsync();
        }


        [HttpPost("[action]")]
        public async Task<ResultStruct> CustomerList(CustomerListVM Scope)
        {
            var user = await _userManager.GetUserAsync(User);

            var CustomerCompanyModel = _customerService.BlockSelectionRange(Scope.Action, Scope.Type);

            if (!string.IsNullOrEmpty(_customerService.Error))
            {
                return Error(new object(), _customerService.Error);
            }


            var FormArr = Enum.GetValues(typeof(CustomerCompany.FromType)).ToArrayDynamic();

            if (!FormArr.Contains(Scope.Form))
            {
                return Error(new object(), "来源错误");
            }


            var BlockInfo = await CustomerCompanyModel
                .Where(m => m.Id == Scope.BlockId)
                .FirstOrDefaultAsync();

            if (BlockInfo == null)
            {
                return Error(new object(), "块不存在");
            }

            var Info = new BlockVM() { };
            var Other = CustomerCompany.FromType.Other;
            var EmailMarketing = CustomerCompany.FromType.EmailMarketing;
            if (Other == Scope.Form || EmailMarketing == Scope.Form)
            {
                Info = new BlockVM()
                {
                    Id = BlockInfo.Id,
                    Title = BlockInfo.Name,
                    Domain = null,
                    From = BlockInfo.From,
                };
            }

            //获取全球搜索域名
            var GlobalSearch = CustomerCompany.FromType.GlobalSearch;
            if (GlobalSearch == Scope.Form)
            {
                var GlobalSearchInfo = await _dbContext.KeywordsDomains.Where(m => m.Id == BlockInfo.RelationId)
                    .FirstOrDefaultAsync();
                if (GlobalSearchInfo == null)
                {
                    return Error(new object(), "全球搜索不存在");
                }

                Info = new BlockVM()
                {
                    Id = BlockInfo.Id,
                    Title = BlockInfo.Name,
                    Url = GlobalSearchInfo.Url,
                    Domain = GlobalSearchInfo.Domain,
                    From = BlockInfo.From,
                };
            }

            //获取客户
            var CustomerModel = _customerService.CustomerSelectionRange(Scope);
            if (!string.IsNullOrEmpty(_customerService.Error))
            {
                return Error(new object(), _customerService.Error);
            }

            var List = await CustomerModel
                .Include(m => m.User)
                .OrderByDescending(m => m.Id)
                .ToPaginateAsync(Scope.Page, Scope.Limit);

            ResCustomerListVM Result = new()
            {
                Info = Info,
                Employees = List,
            };

            return Success(Result);
        }

        [HttpPost(nameof(SetDiyGroup))]
        public async Task<ResultStruct> SetDiyGroup(SetGroupVM Data)
        {
            var res = await _customerService.SetGroup(Data.Group, Data.Ids, SetDataType.Block);
            return res ? Success(new(), "设置成功") : Error(message: _customerService.Error);
        }

        [HttpPost(nameof(SetSource))]
        public async Task<ResultStruct> SetSource(SetSourceVM Data)
        {
            var res = await _customerService.SetSource(Data.Source, Data.Ids, SetDataType.Block);
            return res ? Success(new(), "设置成功") : Error(message: _customerService.Error);
        }

        [HttpPost(nameof(SetLabel))]
        public async Task<ResultStruct> SetLabel(SetLabelVM Data)
        {
            var res = await _customerService.SetLabel(Data.Label, Data.Ids, SetDataType.Block);
            return res ? Success(new(), "设置成功") : Error(message: _customerService.Error);
        }

        [HttpPost(nameof(SetIsPrivate))]
        public ResultStruct SetIsPrivate(SeStateVM Data)
        {
            //var res = await _customerService.SetIsPrivate(Data.Value, Data.Ids, SetDataType.Block);
            var res = false;
            return res ? Success(new(), "操作成功") : Error(message: _customerService.Error);
        }

        [HttpPost(nameof(SetIsIntention))]
        public async Task<ResultStruct> SetIsIntention(SeStateVM Data)
        {
            var res = await _customerService.SetIsIntention(Data.Value, Data.Ids, SetDataType.Block);
            return res ? Success(new(), "操作成功") : Error(message: _customerService.Error);
        }

        [HttpPost(nameof(GetCustomers))]
        public async Task<ResultStruct> GetCustomers(List<int> Ids)
        {
            if (Ids.Count <= 0)
            {
                return Error(new() { }, "参数错误!");
            }

            var user = await _userManager.GetUserAsync(User);
            var Model = user.SettingsObj.OnlyExportValidEmails
                ? _customerService.CustomerWithValidEmailCondition()
                : _customerService.CustomerCondition();

            Model = Model.Where(m => Ids.Contains(m.BlockId));


            var List = await Model.Select(m => new
                {
                    Id = m.Id,
                    Name = m.Name,
                    Email = m.Email,
                    m.PersonalEmail,
                })
                .ToListAsync();

            return Success(List);
        }

        private const int BatchEmailValidationNum = 10;

        /// <summary>
        /// 获取前端需要执行单个块中验证邮箱的轮询次数
        /// </summary>
        /// <param name="blockId"></param>
        /// <returns></returns>
        [HttpGet("[action]/{blockId:int}")]
        public async Task<ResultStruct> GetValidationProgressCount(int blockId)
        {
            var root = _customerService.CustomerCondition();
            root = root.Where(m => m.BlockId == blockId && (m.EmailValidation == EmailValidationType.Unknown ||
                                                            m.PersonalEmailValidation == EmailValidationType.Unknown));

            var count = await root.CountAsync();
            return Success(Math.Ceiling(count / (decimal)BatchEmailValidationNum));
        }

        /// <summary>
        /// 验证单个块中邮箱
        /// </summary>
        /// <param name="blockId"></param>
        /// <param name="anyleadsService"></param>
        /// <returns></returns>
        [HttpPost("[action]/{blockId:int}")]
        public async Task<ResultStruct> VerifyBlockEmails(int blockId, [FromServices] AnyleadsService anyleadsService)
        {
            var root = _customerService.CustomerCondition();
            root = root.Where(m => m.BlockId == blockId && (m.EmailValidation == EmailValidationType.Unknown ||
                                                            m.PersonalEmailValidation == EmailValidationType.Unknown))
                .Take(BatchEmailValidationNum);

            var customers = await root.Select(c => new CustomerModel()
            {
                Id = c.Id,
                Email = c.Email,
                PersonalEmail = c.PersonalEmail,
                EmailValidation = c.EmailValidation,
                PersonalEmailValidation = c.PersonalEmailValidation,
            }).ToListAsync();

            foreach (var customer in customers)
            {
                _dbContext.Entry(customer).State = EntityState.Unchanged;
                if (customer.EmailValidation == EmailValidationType.Unknown)
                    customer.EmailValidation = await ValidateEmail(customer.Email);

                if (customer.PersonalEmailValidation == EmailValidationType.Unknown)
                    customer.PersonalEmailValidation = await ValidateEmail(customer.PersonalEmail);
            }

            await _dbContext.SaveChangesAsync();
            return Success();

            async Task<EmailValidationType> ValidateEmail(string email)
            {
                if (string.IsNullOrWhiteSpace(email))
                    return EmailValidationType.Invalid;

                return (await anyleadsService.ValidateEmail(email))
                    ? EmailValidationType.Validated
                    : EmailValidationType.Invalid;
            }
        }

        [HttpPost("[action]")]
        public async Task<ResultStruct> Create(CustomerCompany customerCompany)
        {
            var res = await _customerService.CreateBlock(customerCompany, true);
            return res ? Success() : Error(message: _customerService.Error);
        }

        [HttpGet("{id:int}")]
        public async Task<ResultStruct> Get(int id)
        {
            var user = await _userManager.GetUserAsync(User);
            var Model = _customerService.CustomerCompanyCondition();
            var row = await Model
                .Where(m => m.Id == id)
                .Include(m => m.DiyGroup)
                .Include(m => m.Source)
                .Include(m => m.Labels)
                .AsSplitQuery()
                .FirstOrDefaultAsync();
            return row == null ? Error(new object(), "获取失败") : Success(row, "获取成功");
        }

        [HttpPut("{id}")]
        public async Task<ResultStruct> Update(CustomerCompany customerCompany)
        {
            if (customerCompany.Id <= 0)
            {
                return Error(new object(), "参数错误");
            }

            var Model = _customerService.CustomerCompanyCondition();

            var row = await Model.Where(m => m.Id == customerCompany.Id)
                .FirstOrDefaultAsync();

            if (row == null)
            {
                return Error(new object(), "数据不存在");
            }

            var NameHash = customerCompany.Name.GetFixedHashCode();

            //去重
            var repeat = await Model
                .Where(m => m.NameHash == NameHash && m.From == customerCompany.From && m.Id != customerCompany.Id)
                .FirstOrDefaultAsync();

            if (repeat != null)
            {
                return Error(new object(), "数据已存在");
            }

            var Time = DateTime.Now;
            row.UpdatedAt = Time;
            row.Name = customerCompany.Name;
            row.NameHash = NameHash;
            row.Url = customerCompany.Url;
            row.Desc = customerCompany.Desc;

            if (customerCompany.SourceId == 0)
            {
                row.SourceId = null;
            }
            else
            {
                row.SourceId = customerCompany.SourceId;
            }

            if (customerCompany.DiyGroupId == 0)
            {
                row.DiyGroupId = null;
            }
            else
            {
                row.DiyGroupId = customerCompany.DiyGroupId;
            }

            var res = await _dbContext.SaveChangesAsync();

            if (res > 0)
            {
                return Success(new() { }, "更新成功");
            }

            return Error(new() { }, "更新失败");
        }

        [HttpPost("delete")]
        public async Task<ResultStruct> Delete(DelectBlockVM vm)
        {
            var id = vm.Id;
            var type = vm.Type;

            var user = await _userManager.GetUserAsync(User);

            var UserType = user.Type;


            var CustomerCompanyModel = _customerService.CustomerCompanyCondition();

            var row = await CustomerCompanyModel
                .Where(m => m.Id == id)
                .FirstOrDefaultAsync();
            if (row == null)
            {
                return Error(new object(), "数据不存在");
            }

            var CustomerModel = _customerService.CustomerCondition();

            var customerCount = CustomerModel.Count(m => m.BlockId == id);

            var status = 0;

            //如果清除的block来自公海且block还存在其他客户信息时只是无公海客户数据时将公海状态移除
            if (type == 3 && customerCount > 0 && row.IsExistPrivate == IsExistPrivateType.Yes)
            {
                var currentBlockPrivateCount = CustomerModel.Where(m => m.BlockId == id && m.IsPrivate == 0).Count();
                if (currentBlockPrivateCount <= 0)
                {
                    row.IsExistPrivate = IsExistPrivateType.NO;

                    _dbContext.Update(row);
                    status = await _dbContext.SaveChangesAsync();

                    if (status > 0)
                    {
                        return Success(new object(), "删除成功");
                    }

                    return Error(new object(), "删除失败");
                }
            }

            if (customerCount > 0)
            {
                await _dbContext.Customer.Where(c => c.BlockId == row.Id).DeleteAsync();
                // return Error(new object(), "存在未清理的客户数据不可删除");
            }


            _dbContext.Remove(row);
            status = await _dbContext.SaveChangesAsync();

            if (status > 0)
            {
                return Success(new object(), "删除成功");
            }

            return Error(new object(), "删除失败");
        }
    }
}